﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Collections;

namespace ProtocolCoder
{
    class Generator
    {
        private string output_directory_;
        private Hashtable variables_;
        private Hashtable message_info_from_name_;
        private OutputPrinter Printer;
        private bool IsServerProto;


        public Generator(string OutputDirectory,
                         Hashtable variables,
                         Hashtable MessageInfosFromName, bool ServerProto)
        {
            output_directory_ = OutputDirectory;
            variables_ = variables;
            message_info_from_name_ = MessageInfosFromName;
            IsServerProto = ServerProto;
        }

        /// <summary>
        /// 生成头文件
        /// </summary>
        /// <returns></returns>
        public bool GenerateFlexFile()
        {
            if (!variables_.ContainsKey("FileName"))
            {
                Console.WriteLine("无法找到与输出文件名称相关的信息");
                return false;
            }
            try
            {
                string filename = output_directory_ + variables_["FileName"] + ".as";
                using (StreamWriter sw = new StreamWriter(filename, false, Encoding.UTF8))
                {
                    Printer = new OutputPrinter(sw, '$');
                    Printer.Print("/********************************************************************\n" +
                                  "**       This head file is generated by program,                   **\n" +
                                  "**            Please do not change it directly.                    **\n" +
                                  "**                   Auther: Fu Yifan                              **\n" +
                                  "********************************************************************/\n\n");



                    //Printer.Print(variables_, "import communication.MessageFactory;\nimport communication.MessageProtocol;\nimport communication.SocketType;");
                    Printer.Print("package\n{\n");
                    Printer.Indent();
                    Printer.Print("import flash.utils.Dictionary;\nimport utils.Logger;\n");
                    string strInc = variables_["Include"] as string;
                    Printer.Print(strInc);
                    Printer.Print("\n");

                    Printer.Print(variables_, "public class $FactoryName$\n{\n");
                    Printer.Indent();

                    // 生成协议ID
                    int MaxIndex = Convert.ToInt32(variables_["MaxIndex"]);
                    ArrayList tempList = new ArrayList(MaxIndex + 1);
                    for (int i = 0; i < MaxIndex + 1; i++)
                        tempList.Add(null);
                    foreach (DictionaryEntry de in message_info_from_name_)
                    {
                        MessageInfo info = (MessageInfo)de.Value;
                        tempList[info.ID] = info;
                    }
                    for (int i = 0; i < MaxIndex + 1; i++)
                    {
                        if (tempList[i] != null)
                        {
                            MessageInfo info = (MessageInfo)tempList[i];
                            Printer.Print(String.Format("static public var {0}:uint = {1};\n", info.Name, info.ID));
                        }
                    }

                    // 协议处理函数
                    foreach (DictionaryEntry de in message_info_from_name_)
                    {
                        MessageInfo info = (MessageInfo)de.Value;
                        if (info.func == null)
                            continue;

                        Printer.Print(variables_, String.Format("\nprivate function Decode{0}(buf:ByteArray, proc:$ProcessorClass$):void", de.Key) + "\n{\n");
                        Printer.Indent();

                        if (IsServerProto == info.ByServer)
                        {
                            //info.
                            Printer.Print("try\n{\n");
                            Printer.Indent();
                            Printer.Print(variables_, String.Format("var pkg:{0}=new {0};\n", info.Type));
                            Printer.Print("pkg.mergeFrom(buf);\n");
                            Printer.Print(String.Format("proc.{0}(pkg);\n", info.func));
                            Printer.Outdent();
                            Printer.Print("}\ncatch(error:Error)\n{\n");
                            Printer.Indent();
                            Printer.Print("Logger.debug(\"Error:\");\nLogger.debug(error.message);\nLogger.debug(error.getStackTrace());\n");
                            Printer.Outdent();
                            Printer.Print("}\n");
                        }
                        Printer.Outdent();
                        Printer.Print("}\n");
                    }

                    // 生成协议到处理函数的映射
                    Printer.Print(variables_, "\nprivate var DecodeFuncArray:Dictionary = new Dictionary();\n\n");
                    Printer.Print(variables_, "public function Init():void\n{\n");
                    Printer.Indent();
                    foreach (DictionaryEntry de in message_info_from_name_)
                    {
                        MessageInfo info = (MessageInfo)de.Value;
                        if (info.func != null)
                            Printer.Print(variables_, String.Format("DecodeFuncArray[{0}] = Decode{0};\n", de.Key));
                    }
                    Printer.Outdent();
                    Printer.Print("}\n\n");

                    // 协议分发处理函数
                    Printer.Print(variables_, "public function Decode(MsgID:uint, buf:ByteArray, proc:$ProcessorClass$):void\n{\n");
                    Printer.Indent();
                    Printer.Print(variables_, "var fun:Function = DecodeFuncArray[MsgID];\n");
                    Printer.Print(variables_, "if (fun != null)\n");
                    Printer.Indent();
                    Printer.Print(variables_, "fun(buf, proc);\n");
                    Printer.Outdent();
                    Printer.Outdent();
                    Printer.Print("}\n");
                    Printer.Outdent();
                    Printer.Print("}\n");
                    Printer.Outdent();
                    Printer.Print("}\n");
                    
                }

                return true;
            }
            catch (System.Exception e)
            {
                Console.WriteLine(e.Message);
                return false;
            }
        }

        public bool Run()
        {
            if (!GenerateFlexFile())
                return false;

            return true;
        }
    }
}
